#include "VXL_File.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include "VoxelRenderer.h"

#include "VFS.h"

char const VXL_File::fileTypeText[] = "Voxel Animation";

void VXL_File::Initialize() {
	if (hva) hva->Initialize();
	if (vxl && !initialized) {
		vxl->seek_start();
		if (vxl->read(vxl_data, vxl->size()) != vxl->size())
			throw;

		unsigned int spos = 0;
		memcpy(&header.fileType[0], &vxl_data[spos], 16);
		spos += 16;
	
		/* Ensure the file type header matches */
		for (unsigned int i = 0; i < 16; i++) {
			if (header.fileType[i] != fileTypeText[i]) {
				header.unknown = 0; /* Ensure the fileType string is null-terminated */
			}
		}

		memcpy(&header.unknown, &vxl_data[spos], sizeof(header.unknown));
		spos += sizeof(header.unknown);

		memcpy(&header.numLimbs, &vxl_data[spos], sizeof(header.numLimbs));
		spos += sizeof(header.numLimbs);

		memcpy(&header.numLimbs2, &vxl_data[spos], sizeof(header.numLimbs2));
		spos += sizeof(header.numLimbs2);

		memcpy(&header.bodySize, &vxl_data[spos], sizeof(header.bodySize));
		spos += sizeof(header.bodySize);
	
		memcpy(&header.startPaletteRemap, &vxl_data[spos], sizeof(header.startPaletteRemap));
		spos += sizeof(header.startPaletteRemap);
	
		memcpy(&header.endPaletteRemap, &vxl_data[spos], sizeof(header.endPaletteRemap));
		spos += sizeof(header.endPaletteRemap);

		/* VXL files seem to have a full-depth palette */
		header.palette.resize(768);
		memcpy(&header.palette[0], &vxl_data[spos], 768);
		spos += 768;

		/* Allocate memory for limb headers, bodies & tailers */
		limbHeaders = new LimbHeader[header.numLimbs];
		limbBodies = new LimbBody[header.numLimbs];
		limbTailers = new LimbTailer[header.numLimbs];

		/* Read all limb headers */
		for (uint32_t i = 0; i != header.numLimbs; i++) {
			readLimbHeader(&limbHeaders[i], spos);
		}

		/* Save file position after all limb headers (start of limb bodies) */
		long pos = spos;
		/* Skip the limb bodies for now (need the tailers first) */
		spos += header.bodySize;

		/* Read all the limb tailers */
		for (uint32_t i = 0; i != header.numLimbs; i++) {
			readLimbTailer(&limbTailers[i], spos);
		}
		/* Read all the limb bodies */
		for (unsigned int i = 0; i < header.numLimbs; i++) {
			spos = pos;
			readLimbBody(i, spos);
		}

		initialized = true;
	}
}

/*
 * The FixedRead passed in MUST be currently seek'ed to the start of all the
 * limb body data
 */
void VXL_File::readLimbBody(uint32_t n, unsigned int& spos) {
	long pos = spos;
	/* Skip to the start of the Span data */
	spos += limbTailers[n].spanStartOff;

	/* Calculate the number of spans in the body */
	uint32_t nSpans = limbTailers[n].xSize * limbTailers[n].ySize;
	/* Allocate memory to hold the spans */
	limbBodies[n].alloc(nSpans);
	
	/* Read in the spanStart & spanEnd offsets */
	memcpy(&limbBodies[n].spanStart[0], &vxl_data[spos], nSpans * sizeof(uint32_t));
	spos += nSpans* sizeof(uint32_t);

	memcpy(&limbBodies[n].spanEnd[0], &vxl_data[spos], nSpans * sizeof(uint32_t));
	spos += nSpans* sizeof(uint32_t);

	LimbBody::Span::Voxel* tmpVox = new LimbBody::Span::Voxel[limbTailers[n].zSize];

	//Utils::ScopedArray<LimbBody::Span::Voxel> tmpVox_free(tmpVox);
	pos = spos;

	for (uint32_t j = 0; j < nSpans; j++) {
		/* Skip any null spans */
		if (limbBodies[n].spanStart[j] == -1 || limbBodies[n].spanEnd[j] == -1) {
			continue;
		}
		if (spos != pos + limbBodies[n].spanStart[j]) {
			spos = pos + limbBodies[n].spanStart[j];
		}
		/* Decompress the voxels in this span, into the temporary voxel array */
		limbBodies[n].span[j].numVoxels = decompressVoxels(tmpVox, limbTailers[n].zSize, spos);
		limbBodies[n].span[j].alloc();
		for (unsigned int k = 0; k != limbBodies[n].span[j].numVoxels; k++) {
			limbBodies[n].span[j].voxel[k] = tmpVox[k];
		}

		/* All voxel spans seem to end with 2 bytes of garbage, so eat that.  Some have more, but the seek
		 * at the top of the loop will take care of it */
		spos += 2;
	}
}

uint8_t VXL_File::decompressVoxels(LimbBody::Span::Voxel* voxel, uint8_t zSz, unsigned int& spos) {
	unsigned int z = 0;
	uint8_t skip, nv, nv2, numZ;
	for (unsigned int i = 0; i != zSz; i++) {
		voxel[i].used = false;		/* Mark all as unused */
	}

	while (z != zSz) {
		memcpy(&skip, &vxl_data[spos], sizeof(skip));
		spos += sizeof(skip);
		z += skip;

		if (z >= zSz) {
			break;
		}
		
		memcpy(&nv, &vxl_data[spos], sizeof(nv));
		spos += sizeof(nv);

		for (unsigned int i = 0; i != nv; i++) {
			voxel[z].colour = vxl_data[spos++];
			voxel[z].normal = vxl_data[spos++];

			voxel[z].used = true;
			z++;
		}
		numZ = z;
		memcpy(&nv2, &vxl_data[spos], sizeof(nv2));
		spos += sizeof(nv2);		
	}
	return numZ;
}

void VXL_File::readLimbHeader(LimbHeader* lh, unsigned int& spos) {
	memcpy(&lh->name[0], &vxl_data[spos], 16);
	spos += 16;
	
	memcpy(&lh->number, &vxl_data[spos], sizeof(lh->number));
	spos += sizeof(lh->number);

	memcpy(&lh->unknown, &vxl_data[spos], sizeof(lh->unknown));
	spos += sizeof(lh->unknown);

	memcpy(&lh->unknown2, &vxl_data[spos], sizeof(lh->unknown2));
	spos += sizeof(lh->unknown2);
}

void VXL_File::readLimbTailer(LimbTailer* lt, unsigned int& spos) {
	memcpy(&lt->spanStartOff, &vxl_data[spos], sizeof(lt->spanStartOff));
	spos += sizeof(lt->spanStartOff);	

	memcpy(&lt->spanEndOff, &vxl_data[spos], sizeof(lt->spanEndOff));
	spos += sizeof(lt->spanEndOff);		
	
	memcpy(&lt->spanDataOff, &vxl_data[spos], sizeof(lt->spanDataOff));
	spos += sizeof(lt->spanDataOff);	
	
	memcpy(&lt->scale, &vxl_data[spos], sizeof(lt->scale));
	spos += sizeof(lt->scale);
	
	memcpy(lt->transform, &vxl_data[spos], sizeof(lt->transform));
	spos += sizeof(lt->transform);

	memcpy(&lt->minBounds[0], &vxl_data[spos], 3 * sizeof(float));
	spos += 3 * sizeof(float);

	memcpy(&lt->maxBounds[0], &vxl_data[spos], 3 * sizeof(float));
	spos += 3 * sizeof(float);
		
	memcpy(&lt->xSize, &vxl_data[spos], sizeof(lt->xSize));
	spos += sizeof(lt->xSize);
	
	memcpy(&lt->ySize, &vxl_data[spos], sizeof(lt->ySize));
	spos += sizeof(lt->ySize);

	memcpy(&lt->zSize, &vxl_data[spos], sizeof(lt->zSize));
	spos += sizeof(lt->zSize);

	memcpy(&lt->normalType, &vxl_data[spos], sizeof(lt->normalType));
	spos += sizeof(lt->normalType);
}


VXL_File::~VXL_File() {
	delete[] limbHeaders;
	delete[] limbTailers;
	delete[] limbBodies;
}

bool VXL_File::getVoxel(uint8_t x, uint8_t y, uint8_t z, LimbBody::Span::Voxel* vx) {
	unsigned int sn = (y * limbTailers[currentLimb].xSize) + x;
	if (limbBodies[currentLimb].spanStart[sn] == -1 || limbBodies[currentLimb].spanEnd[sn] == -1) {
		return false;
	}
	if (z >= limbBodies[currentLimb].span[sn].numVoxels) {
		return false;
	}
	LimbBody::Span::Voxel* tmp = &limbBodies[currentLimb].span[sn].voxel[z];
	if (tmp->used) {
		*vx = *tmp;
		return true;
	} else {
		return false;
	}
}

const std::vector<unsigned char>& VXL_File::getPalette() {
	return header.palette;
}

void VXL_File::getXYZNormal(uint8_t n, float& x, float& y, float& z) {
	if (limbTailers[currentLimb].normalType == 2) {
		if (n >= TS_NUM_NORMALS) {
			n = TS_NUM_NORMALS - 1;
		}
		x = TSNormals[n][0];
		y = TSNormals[n][1];
		z = TSNormals[n][2];
	} 
	else if (limbTailers[currentLimb].normalType == 4) {
		if (n >= RA2_NUM_NORMALS) {
			n = RA2_NUM_NORMALS - 1;
		}
		x = RA2Normals[n][0];
		y = RA2Normals[n][1];
		z = RA2Normals[n][2];
	} 
}

void VXL_File::getSize(uint8_t& x, uint8_t& y, uint8_t& z) {
	x = limbTailers[currentLimb].xSize;
	y = limbTailers[currentLimb].ySize;
	z = limbTailers[currentLimb].zSize;
}

void VXL_File::getBounds(float* min, float* max) {
	min[0] = limbTailers[currentLimb].minBounds[0];
	min[1] = limbTailers[currentLimb].minBounds[1];
	min[2] = limbTailers[currentLimb].minBounds[2];

	max[0] = limbTailers[currentLimb].maxBounds[0];
	max[1] = limbTailers[currentLimb].maxBounds[1];
	max[2] = limbTailers[currentLimb].maxBounds[2];
}

void VXL_File::getTotalBounds(int& width, int& height) {
	for (unsigned int i = 0; i != header.numLimbs; i++) {
		const int cx = this->limbTailers[i].xSize;
		const int cy = this->limbTailers[i].ySize;
		const int cz = this->limbTailers[i].zSize;
		const int l = ceil(sqrt((cx * cx + cy * cy + cz * cz) / 4.0));
		const int cl = 2 * l;
		width = std::max(cl, width);
		height = std::max(cl, height);
	}
}

float VXL_File::getScale() {
	return limbTailers[currentLimb].scale;
}

void VXL_File::loadGLMatrix(float* m) {
	/* OpenGL matrices are laid out thus:
	 * [ 0] [ 4] [ 8] [12]
	 * [ 1] [ 5] [ 9] [13]
	 * [ 2] [ 6] [10] [14]
	 * [ 3] [ 7] [11] [15]
	 *
	 * We need to load the matrix with
	 * [0][0] [0][1] [0][2] [0][3]
	 * [1][0] [1][1] [1][2] [1][3]
	 * [2][0] [2][1] [2][2] [2][3]
	 *    0      0      0      1
	 */
	m[0]  = limbTailers[currentLimb].transform[0][0];
	m[1]  = limbTailers[currentLimb].transform[1][0];
	m[2]  = limbTailers[currentLimb].transform[2][0];
	m[3]  = 0;
	m[4]  = limbTailers[currentLimb].transform[0][1];
	m[5]  = limbTailers[currentLimb].transform[1][1];
	m[6]  = limbTailers[currentLimb].transform[2][1];
	m[7]  = 0;
	m[8]  = limbTailers[currentLimb].transform[0][2];
	m[9]  = limbTailers[currentLimb].transform[1][2];
	m[10] = limbTailers[currentLimb].transform[2][2];
	m[11] = 0;
	m[12] = limbTailers[currentLimb].transform[0][3];
	m[13] = limbTailers[currentLimb].transform[1][3];
	m[14] = limbTailers[currentLimb].transform[2][3];
	m[15] = 1;
}

uint32_t VXL_File::getNumLimbs() {
	return header.numLimbs;
}

std::string VXL_File::limbName() {
	return reinterpret_cast<char const*>(limbHeaders[currentLimb].name);
}

void VXL_File::setCurrentLimb(uint32_t l) {
	currentLimb = l;
}

void VXL_File::setCurrentLimb(std::string const& name) {
	for (uint32_t i = 0; i != header.numLimbs; i++) {
		if (strcmp(reinterpret_cast<char const*>(&limbHeaders[i].name[0]), name.c_str()) == 0) {
			currentLimb = i;
			return;
		}
	}
}

/*
 * This table of normals was taken from the OS Voxel Tools SVN code repository on 2008-08-08.
 * 
 * Thanks to: Banshee, Stucuk, Will, Koen and Plasmadroid.
 *
 * Get the latest versions of OS Voxel Tools, OS HVA Builder & other modding tools from:
 * Project Perfect Mod (http://www.ppmsite.com/)
 * CnC Source (http://www.cnc-source.com/)
 */
float const VXL_File::RA2Normals[RA2_NUM_NORMALS][3] = {
	{ 0.526578009128571f, -0.359620988368988f, -0.770317018032074f },
	{ 0.150481998920441f, 0.43598398566246f, 0.887283980846405f },
	{ 0.414195001125336f, 0.738255023956299f, -0.532374024391174f },
	{ 0.0751520022749901f, 0.916248977184296f, -0.393498003482819f },
	{ -0.316148996353149f, 0.930736005306244f, -0.183792993426323f },
	{ -0.773819029331207f, 0.623333990573883f, -0.112510003149509f },
	{ -0.900842010974884f, 0.428537011146545f, -0.0695680007338524f },
	{ -0.998942017555237f, -0.010971000418067f, 0.0446650013327599f },
	{ -0.979761004447937f, -0.157670006155968f, -0.123323999345303f },
	{ -0.911274015903473f, -0.362370997667313f, -0.195620000362396f },
	{ -0.624068975448608f, -0.720941007137299f, -0.301301002502441f },
	{ -0.310173004865646f, -0.809345006942749f, -0.498751997947693f },
	{ 0.146613001823425f, -0.815819025039673f, -0.559414029121399f },
	{ -0.716516017913818f, -0.694356024265289f, -0.0668879970908165f },
	{ 0.503971993923187f, -0.114202000200748f, -0.856136977672577f },
	{ 0.455491006374359f, 0.872627019882202f, -0.176210999488831f },
	{ -0.00500999996438622f, -0.114372998476028f, -0.993425011634827f },
	{ -0.104675002396107f, -0.32770100235939f, -0.938965022563934f },
	{ 0.560411989688873f, 0.752588987350464f, -0.345755994319916f },
	{ -0.0605759993195534f, 0.821627974510193f, -0.566796004772186f },
	{ -0.302341014146805f, 0.797007024288178f, -0.52284699678421f },
	{ -0.671543002128601f, 0.670740008354187f, -0.314862996339798f },
	{ -0.778401017189026f, -0.128356993198395f, 0.614504992961884f },
	{ -0.924049973487854f, 0.278382003307343f, -0.261985003948212f },
	{ -0.699773013591766f, -0.550490975379944f, -0.455278009176254f },
	{ -0.568247973918915f, -0.517189025878906f, -0.640007972717285f },
	{ 0.0540979988873005f, -0.932864010334015f, -0.356142997741699f },
	{ 0.758382022380829f, 0.572893023490906f, -0.31088799238205f },
	{ 0.00362000009045005f, 0.305025994777679f, -0.952337026596069f },
	{ -0.0608499981462956f, -0.986886024475098f, -0.149510994553566f },
	{ 0.635230004787445f, 0.0454780012369156f, -0.770982980728149f },
	{ 0.521704971790314f, 0.241309002041817f, -0.818287014961243f },
	{ 0.269403994083405f, 0.635424971580505f, -0.723640978336334f },
	{ 0.0456760004162788f, 0.672753989696503f, -0.73845499753952f },
	{ -0.180510997772217f, 0.674656987190247f, -0.715718984603882f },
	{ -0.397130995988846f, 0.636640012264252f, -0.661041975021362f },
	{ -0.552003979682922f, 0.472514986991882f, -0.687038004398346f },
	{ -0.772170007228851f, 0.0830899998545647f, -0.629960000514984f },
	{ -0.669818997383118f, -0.119533002376556f, -0.732840001583099f },
	{ -0.540454983711243f, -0.318444013595581f, -0.77878201007843f },
	{ -0.386135011911392f, -0.522789001464844f, -0.759993970394135f },
	{ -0.26146599650383f, -0.688566982746124f, -0.676394999027252f },
	{ -0.0194119997322559f, -0.696102976799011f, -0.717679977416992f },
	{ 0.303568989038467f, -0.481844007968903f, -0.821992993354797f },
	{ 0.681939005851746f, -0.195129007101059f, -0.704900026321411f },
	{ -0.244889006018639f, -0.116562001407146f, -0.962518990039825f },
	{ 0.800759017467499f, -0.0229790005832911f, -0.598546028137207f },
	{ -0.370274990797043f, 0.0955839976668358f, -0.923991024494171f },
	{ -0.330671012401581f, -0.326577991247177f, -0.885439991950989f },
	{ -0.163220003247261f, -0.527579009532928f, -0.833679020404816f },
	{ 0.126389995217323f, -0.313145995140076f, -0.941256999969482f },
	{ 0.349548012018204f, -0.272226005792618f, -0.896498024463654f },
	{ 0.239917993545532f, -0.0858250036835671f, -0.966992020606995f },
	{ 0.390845000743866f, 0.0815370008349419f, -0.916837990283966f },
	{ 0.2552669942379f, 0.268696993589401f, -0.928785026073456f },
	{ 0.146245002746582f, 0.480437994003296f, -0.864749014377594f },
	{ -0.326016008853912f, 0.478455990552902f, -0.815348982810974f },
	{ -0.46968200802803f, -0.112519003450871f, -0.875635981559753f },
	{ 0.818440020084381f, -0.258520007133484f, -0.513150990009308f },
	{ -0.474317997694015f, 0.292237997055054f, -0.830433011054993f },
	{ 0.778943002223969f, 0.395841985940933f, -0.486371010541916f },
	{ 0.624094009399414f, 0.39377298951149f, -0.674870014190674f },
	{ 0.740885972976685f, 0.203833997249603f, -0.639953017234802f },
	{ 0.480217009782791f, 0.565768003463745f, -0.670297026634216f },
	{ 0.380930006504059f, 0.424535006284714f, -0.821377992630005f },
	{ -0.0934220030903816f, 0.501124024391174f, -0.860318005084991f },
	{ -0.236485004425049f, 0.296198010444641f, -0.925387024879456f },
	{ -0.131531000137329f, 0.0939590036869049f, -0.986849009990692f },
	{ -0.823562026023865f, 0.29577699303627f, -0.484005987644196f },
	{ 0.611065983772278f, -0.624303996562958f, -0.486663997173309f },
	{ 0.0694959983229637f, -0.520330011844635f, -0.851132988929748f },
	{ 0.226521998643875f, -0.664879024028778f, -0.711775004863739f },
	{ 0.471307992935181f, -0.568903982639313f, -0.673956990242004f },
	{ 0.38842499256134f, -0.74262398481369f, -0.545560002326965f },
	{ 0.783675014972687f, -0.480729013681412f, -0.393384993076324f },
	{ 0.962393999099731f, 0.135675996541977f, -0.235348999500275f },
	{ 0.876607000827789f, 0.172033995389938f, -0.449405997991562f },
	{ 0.633405029773712f, 0.589793026447296f, -0.500940978527069f },
	{ 0.182275995612144f, 0.800657987594605f, -0.570720970630646f },
	{ 0.177002996206284f, 0.764133989810944f, 0.620297014713287f },
	{ -0.544016003608704f, 0.675514996051788f, -0.497720986604691f },
	{ -0.679296970367432f, 0.286466985940933f, -0.675642013549805f },
	{ -0.590390980243683f, 0.0913690030574799f, -0.801928997039795f },
	{ -0.824360013008118f, -0.133123993873596f, -0.550189018249512f },
	{ -0.715794026851654f, -0.334542006254196f, -0.612960994243622f },
	{ 0.174285992980003f, -0.8924840092659f, 0.416049003601074f },
	{ -0.0825280025601387f, -0.837122976779938f, -0.54075300693512f },
	{ 0.283331006765366f, -0.88087397813797f, -0.379189014434814f },
	{ 0.675134003162384f, -0.42662701010704f, -0.601817011833191f },
	{ 0.843720018863678f, -0.512335002422333f, -0.16015599668026f },
	{ 0.977303981781006f, -0.0985559970140457f, -0.187519997358322f },
	{ 0.84629499912262f, 0.52267199754715f, -0.102946996688843f },
	{ 0.677141010761261f, 0.721324980258942f, -0.145501002669334f },
	{ 0.320964992046356f, 0.870891988277435f, -0.372193992137909f },
	{ -0.178977996110916f, 0.911532998085022f, -0.37023600935936f },
	{ -0.447169005870819f, 0.826700985431671f, -0.341473996639252f },
	{ -0.703203022480011f, 0.496327996253967f, -0.50908100605011f },
	{ -0.977181017398834f, 0.0635629966855049f, -0.202674001455307f },
	{ -0.878170013427734f, -0.412937998771667f, 0.241455003619194f },
	{ -0.835830986499786f, -0.358550012111664f, -0.415728002786636f },
	{ -0.499173998832703f, -0.693432986736298f, -0.519591987133026f },
	{ -0.188788995146751f, -0.923753023147583f, -0.333225011825562f },
	{ 0.19225400686264f, -0.969361007213593f, -0.152896001935005f },
	{ 0.515940010547638f, -0.783906996250153f, -0.345391988754272f },
	{ 0.90592497587204f, -0.300951987504959f, -0.297870993614197f },
	{ 0.991111993789673f, -0.127746000885963f, 0.0371069982647896f },
	{ 0.995135009288788f, 0.0984240025281906f, -0.0043830000795424f },
	{ 0.760123014450073f, 0.646277010440826f, 0.0673670023679733f },
	{ 0.205220997333527f, 0.95958000421524f, -0.192590996623039f },
	{ -0.0427500009536743f, 0.979512989521027f, -0.196790993213654f },
	{ -0.438017010688782f, 0.898926973342895f, 0.00849200040102005f },
	{ -0.821994006633759f, 0.480785012245178f, -0.305238991975784f },
	{ -0.899917006492615f, 0.0817100033164024f, -0.428337007761002f },
	{ -0.926612019538879f, -0.144618004560471f, -0.347095996141434f },
	{ -0.79365998506546f, -0.557792007923126f, -0.242838993668556f },
	{ -0.431349992752075f, -0.847778975963593f, -0.308557987213135f },
	{ -0.00549199990928173f, -0.964999973773956f, 0.262192994356155f },
	{ 0.587904989719391f, -0.804026007652283f, -0.0889400020241737f },
	{ 0.699492990970612f, -0.667685985565186f, -0.254765003919601f },
	{ 0.889303028583527f, 0.35979500412941f, -0.282290995121002f },
	{ 0.780972003936768f, 0.197036996483803f, 0.592671990394592f },
	{ 0.520120978355408f, 0.506695985794067f, 0.687556982040405f },
	{ 0.403894990682602f, 0.693961024284363f, 0.59605997800827f },
	{ -0.154982998967171f, 0.899236023426056f, 0.409090012311935f },
	{ -0.65733802318573f, 0.537168025970459f, 0.528542995452881f },
	{ -0.746195018291473f, 0.334091007709503f, 0.57582700252533f },
	{ -0.624952018260956f, -0.0491439998149872f, 0.77911502122879f },
	{ 0.318141013383865f, -0.254714995622635f, 0.913185000419617f },
	{ -0.555896997451782f, 0.405294001102447f, 0.725751996040344f },
	{ -0.794434010982513f, 0.0994059965014458f, 0.599160015583038f },
	{ -0.64036101102829f, -0.689463019371033f, 0.3384949862957f },
	{ -0.126712992787361f, -0.734094977378845f, 0.667119979858398f },
	{ 0.105457000434399f, -0.780816972255707f, 0.615795016288757f },
	{ 0.407992988824844f, -0.480915993452072f, 0.776054978370666f },
	{ 0.69513601064682f, -0.545120000839233f, 0.468647003173828f },
	{ 0.973191022872925f, -0.00648899981752038f, 0.229908004403114f },
	{ 0.946893990039825f, 0.31750899553299f, -0.0507990010082722f },
	{ 0.563583016395569f, 0.825612008571625f, 0.0271829999983311f },
	{ 0.325773000717163f, 0.945423007011414f, 0.00694900006055832f },
	{ -0.171820998191834f, 0.985096991062164f, -0.00781499966979027f },
	{ -0.670440971851349f, 0.739938974380493f, 0.0547689981758594f },
	{ -0.822980999946594f, 0.554961979389191f, 0.121321998536587f },
	{ -0.96619302034378f, 0.117857001721859f, 0.229306995868683f },
	{ -0.953769028186798f, -0.294703990221024f, 0.0589450001716614f },
	{ -0.864386975765228f, -0.50272798538208f, -0.0100149996578693f },
	{ -0.530609011650085f, -0.842006027698517f, -0.0973659977316856f },
	{ -0.16261799633503f, -0.984075009822845f, 0.071772001683712f },
	{ 0.081446997821331f, -0.996011018753052f, 0.0364390015602112f },
	{ 0.745984017848968f, -0.665962994098663f, 0.000761999981477857f },
	{ 0.942057013511658f, -0.329268991947174f, -0.0641060024499893f },
	{ 0.939701974391937f, -0.2810899913311f, 0.19480299949646f },
	{ 0.771214008331299f, 0.550670027732849f, 0.319362998008728f },
	{ 0.641348004341126f, 0.730690002441406f, 0.234020993113518f },
	{ 0.0806820020079613f, 0.996690988540649f, 0.00987899955362082f },
	{ -0.0467250011861324f, 0.976643025875092f, 0.209725007414818f },
	{ -0.531076014041901f, 0.821000993251801f, 0.209562003612518f },
	{ -0.695815026760101f, 0.65599000453949f, 0.292434990406036f },
	{ -0.97612202167511f, 0.21670900285244f, -0.0149130001664162f },
	{ -0.961660981178284f, -0.144128993153572f, 0.233313992619514f },
	{ -0.77208399772644f, -0.613646984100342f, 0.165298998355865f },
	{ -0.449600011110306f, -0.836059987545013f, 0.314426004886627f },
	{ -0.392699986696243f, -0.914615988731384f, 0.0962470024824142f },
	{ 0.390588998794556f, -0.919470012187958f, 0.0448900014162064f },
	{ 0.582529008388519f, -0.799197971820831f, 0.148127004504204f },
	{ 0.866430997848511f, -0.489811986684799f, 0.0968639999628067f },
	{ 0.904586970806122f, 0.11149799823761f, 0.411449998617172f },
	{ 0.953536987304687f, 0.232329994440079f, 0.191806003451347f },
	{ 0.497310996055603f, 0.770802974700928f, 0.398176997900009f },
	{ 0.194066002964973f, 0.956319987773895f, 0.218611001968384f },
	{ 0.422876000404358f, 0.882275998592377f, 0.206797003746033f },
	{ -0.373796999454498f, 0.849565982818604f, 0.372173994779587f },
	{ -0.534497022628784f, 0.714022994041443f, 0.452199995517731f },
	{ -0.881826996803284f, 0.237159997224808f, 0.407597988843918f },
	{ -0.904947996139526f, -0.0140690002590418f, 0.425289005041122f },
	{ -0.751827001571655f, -0.512817025184631f, 0.414458006620407f },
	{ -0.50101500749588f, -0.697916984558105f, 0.511758029460907f },
	{ -0.235190004110336f, -0.925922989845276f, 0.295554995536804f },
	{ 0.228982999920845f, -0.953939974308014f, 0.193819001317024f },
	{ 0.734025001525879f, -0.634898006916046f, 0.241062000393867f },
	{ 0.913752973079681f, -0.0632530003786087f, -0.401315987110138f },
	{ 0.905735015869141f, -0.161486998200417f, 0.391874998807907f },
	{ 0.858929991722107f, 0.342445999383926f, 0.380748987197876f },
	{ 0.624486029148102f, 0.60758101940155f, 0.490776985883713f },
	{ 0.289263993501663f, 0.857478976249695f, 0.425507992506027f },
	{ 0.0699680000543594f, 0.902168989181519f, 0.425671011209488f },
	{ -0.28617998957634f, 0.940699994564056f, 0.182164996862411f },
	{ -0.574012994766235f, 0.805118978023529f, -0.149308994412422f },
	{ 0.111258000135422f, 0.0997179970145225f, -0.988776028156281f },
	{ -0.305393010377884f, -0.944227993488312f, -0.123159997165203f },
	{ -0.601166009902954f, -0.78957599401474f, 0.123162999749184f },
	{ -0.290645003318787f, -0.812139987945557f, 0.505918979644775f },
	{ -0.064920000731945f, -0.877162992954254f, 0.475784987211227f },
	{ 0.408300995826721f, -0.862215995788574f, 0.299789011478424f },
	{ 0.566097021102905f, -0.725566029548645f, 0.391263991594315f },
	{ 0.839363992214203f, -0.427386999130249f, 0.335869014263153f },
	{ 0.818899989128113f, -0.0413050018250942f, 0.572448015213013f },
	{ 0.719784021377564f, 0.414997011423111f, 0.556496977806091f },
	{ 0.881744027137756f, 0.450269997119904f, 0.140659004449844f },
	{ 0.40182301402092f, -0.898220002651215f, -0.178151994943619f },
	{ -0.0540199987590313f, 0.791343986988068f, 0.608980000019074f },
	{ -0.293774008750916f, 0.763993978500366f, 0.574464976787567f },
	{ -0.450798004865646f, 0.610346972942352f, 0.651350975036621f },
	{ -0.638221025466919f, 0.186693996191025f, 0.746873021125793f },
	{ -0.872870028018951f, -0.257126986980438f, 0.414707988500595f },
	{ -0.587257027626038f, -0.521709978580475f, 0.618827998638153f },
	{ -0.353657990694046f, -0.641973972320557f, 0.680290997028351f },
	{ 0.0416489988565445f, -0.611272990703583f, 0.79032301902771f },
	{ 0.348342001438141f, -0.779182970523834f, 0.521086990833282f },
	{ 0.499166995286942f, -0.622440993785858f, 0.602825999259949f },
	{ 0.790018975734711f, -0.3038310110569f, 0.53250002861023f },
	{ 0.660117983818054f, 0.0607330016791821f, 0.748701989650726f },
	{ 0.604920983314514f, 0.29416099190712f, 0.739960014820099f },
	{ 0.38569700717926f, 0.379346013069153f, 0.841032028198242f },
	{ 0.239693000912666f, 0.207875996828079f, 0.948332011699677f },
	{ 0.012622999958694f, 0.258531987667084f, 0.965919971466065f },
	{ -0.100556999444962f, 0.457147002220154f, 0.883687973022461f },
	{ 0.0469669997692108f, 0.628588020801544f, 0.776319026947021f },
	{ -0.430391013622284f, -0.445405006408691f, 0.785097002983093f },
	{ -0.434291005134583f, -0.196227997541428f, 0.879139006137848f },
	{ -0.256637006998062f, -0.33686700463295f, 0.905902028083801f },
	{ -0.131372004747391f, -0.158910006284714f, 0.978514015674591f },
	{ 0.102379001677036f, -0.208766996860504f, 0.972591996192932f },
	{ 0.195686995983124f, -0.450129002332687f, 0.871258020401001f },
	{ 0.627318978309631f, -0.42314800620079f, 0.653770983219147f },
	{ 0.687439024448395f, -0.171582996845245f, 0.70568197965622f },
	{ 0.275920003652573f, -0.021254999563098f, 0.960946023464203f },
	{ 0.459367007017136f, 0.157465994358063f, 0.874177992343903f },
	{ 0.285394996404648f, 0.583184003829956f, 0.760555982589722f },
	{ -0.812174022197723f, 0.460303008556366f, 0.358460992574692f },
	{ -0.189068004488945f, 0.641223013401032f, 0.743698000907898f },
	{ -0.338874995708466f, 0.476480007171631f, 0.811251997947693f },
	{ -0.920993983745575f, 0.347185999155045f, 0.176726996898651f },
	{ 0.0406389981508255f, 0.024465000256896f, 0.998874008655548f },
	{ -0.739131987094879f, -0.353747010231018f, 0.573189973831177f },
	{ -0.603511989116669f, -0.286615014076233f, 0.744059979915619f },
	{ -0.188675999641418f, -0.547058999538422f, 0.815554022789001f },
	{ -0.0260450001806021f, -0.397819995880127f, 0.917093992233276f },
	{ 0.267897009849548f, -0.649040997028351f, 0.712023019790649f },
	{ 0.518245995044708f, -0.28489100933075f, 0.806385993957519f },
	{ 0.493450999259949f, -0.0665329992771149f, 0.867224991321564f },
	{ -0.328188002109528f, 0.140250995755196f, 0.934143006801605f },
	{ -0.328188002109528f, 0.140250995755196f, 0.934143006801605f },
	{ -0.328188002109528f, 0.140250995755196f, 0.934143006801605f },
	{ -0.328188002109528f, 0.140250995755196f, 0.934143006801605 }

};

float const VXL_File::TSNormals[TS_NUM_NORMALS][3] = {
	{ 0.671213984489441f, 0.198492005467415f, -0.714193999767303f, },
	{ 0.269643008708954f, 0.584393978118897f, -0.765359997749329f, },
	{ -0.0405460000038147f, 0.0969879999756813f, -0.994458973407745f, },
	{ -0.572427988052368f, -0.0919139981269836f, -0.814786970615387f, },
	{ -0.171400994062424f, -0.572709977626801f, -0.801639020442963f, },
	{ 0.362556993961334f, -0.30299898982048f, -0.881331026554108f, },
	{ 0.810347020626068f, -0.348971992731094f, -0.470697999000549f, },
	{ 0.103961996734142f, 0.938672006130218f, -0.328767001628876f, },
	{ -0.32404699921608f, 0.587669014930725f, -0.741375982761383f, },
	{ -0.800864994525909f, 0.340460985898972f, -0.492646992206574f, },
	{ -0.665498018264771f, -0.590147018432617f, -0.456988990306854f, },
	{ 0.314767003059387f, -0.803001999855042f, -0.506072998046875f, },
	{ 0.972629010677338f, 0.151076003909111f, -0.176550000905991f, },
	{ 0.680290997028351f, 0.684235990047455f, -0.262726992368698f, },
	{ -0.520079016685486f, 0.827777028083801f, -0.210482999682426f, },
	{ -0.961643993854523f, -0.179001003503799f, -0.207846999168396f, },
	{ -0.262713998556137f, -0.937451004981995f, -0.228401005268097f, },
	{ 0.219706997275352f, -0.971301019191742f, 0.0911249965429306f, },
	{ 0.923807978630066f, -0.229975000023842f, 0.306086987257004f, },
	{ -0.0824889987707138f, 0.970659971237183f, 0.225866004824638f, },
	{ -0.591798007488251f, 0.696789979934692f, 0.405288994312286f, },
	{ -0.925296008586884f, 0.36660099029541f, 0.0971110016107559f, },
	{ -0.705051004886627f, -0.687775015830994f, 0.172828003764153f, },
	{ 0.732400000095367f, -0.680366992950439f, -0.0263049993664026f, },
	{ 0.855162024497986f, 0.37458199262619f, 0.358310997486114f, },
	{ 0.473006010055542f, 0.836480021476746f, 0.276704996824265f, },
	{ -0.0976170003414154f, 0.654111981391907f, 0.750072002410889f, },
	{ -0.904124021530151f, -0.153724998235703f, 0.398658007383347f, },
	{ -0.211915999650955f, -0.858089983463287f, 0.467732012271881f, },
	{ 0.500226974487305f, -0.67440801858902f, 0.543090999126434f, },
	{ 0.584538996219635f, -0.110248997807503f, 0.8038409948349f, },
	{ 0.437373012304306f, 0.454643994569778f, 0.775888979434967f, },
	{ -0.0424409992992878f, 0.0833180025219917f, 0.995618999004364f, },
	{ -0.596251010894775f, 0.220131993293762f, 0.772028028964996f, },
	{ -0.50645500421524f, -0.396977007389069f, 0.765448987483978f, },
	{ 0.0705690011382103f, -0.478473991155624f, 0.875262022018433f, },
};


void VXL_File::Draw(const int x_off, const int y_off, const int direction, DrawingSurface& dst, const Palet* p) {
	this->hva = boost::shared_ptr<HVA_File>(new HVA_File(vfs.open("shad.hva")));
	this->vxl = vfs.open("shad.vxl");

	Initialize();
	if (!hva || !hva->initialized || !initialized) return;

	DrawingSurface* vxl_ds = voxelrenderer.render(this, this->hva.get(), -(double)direction / 256.0 * 360 + 45, p);
	for (int y = 0; y < vxl_ds->Get_Height(); y++) {
			// rows inverted!		
		unsigned char* src = (unsigned char*)vxl_ds->Get_Lower_Bound() + vxl_ds->Get_Stride() * (vxl_ds->Get_Height() - y - 1);
		unsigned char* dst_row = (unsigned char*)(dst.Get_Lower_Bound() + (y_off + y) * dst.Get_Stride()) + x_off * 3;
		if (!dst.Within_Bounds(dst_row)) continue;
		for (int x = 0; x < vxl_ds->Get_Width(); x++) {
			// only non-transparent pixels
			if (*(src + x * 4 + 3) > 0)
				memcpy(dst_row + x * 3, src + x * 4, 3);
		}
	}
}
